/*
Copyright (C) 2012 Brady Vidovic

This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
package ftr.gson;

import org.apache.commons.io.FilenameUtils;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
import java.text.SimpleDateFormat;
import java.util.Arrays;
import static btv.tools.BTVTools.*;
import static ftr.tools.Constants.*;

/**
 * Recording class represents a 4tr Recording
 * @author bvidovic
 */
public class Recording
{        
        
    //todo: expose these JSON variables as needed
    private String Actors, Category, ChannelDisplayName, SubTitle, Title, Rating, Description, ScheduleId, EpisodeNumberDisplay;//, ChannelId, Director, RecordingFileName, ScheduleName;
    private Integer EpisodeNumber, SeriesNumber;//, ChannelType, EpisodeNumberTotal, EpisodePart, EpisodePartTotal, Flags, KeepUntilMode, SchedulePriority, StarRating;
    private boolean IsPartialRecording;//,IsPartOfSeries, IsPremiere, IsRepeat, PendingDelete;
    private FTRDate RecordingStartTime;//, RecordingStopTime, ProgramStartTime, ProgramStopTime;    
    
    //non JSON:
    private File recordingFile;
    private String year, tvdbId, RecordingId, extension, pathNoExtension, baseName, originalPath;    
    private boolean isMultiPart, manuallyArchived;//multi part means this single recording contains >1 TVDB episode  
    private String seasonEpisodeNaming;      
    
    /*Sample:
        {
            "Actors": "Christina Applegate;Will Arnett;Maya Rudolph",
            "Category": "Series",
            "ChannelDisplayName": "KBJR6",
            "ChannelId": "b2c13304-9a3b-4c2c-90f0-da5576cd1415",
            "ChannelType": 0,
            "Description": "When Reagan and Ava's idol acquires the show, they get a new militant boss; Chris helps Reed refurbish his motorcycle. [y:2011] [tvdb:248943]",
            "Director": "",
            "EpisodeNumber": 18,
            "EpisodeNumberDisplay": "18",
            "EpisodeNumberTotal": null,
            "EpisodePart": 1,
            "EpisodePartTotal": 0,
            "Flags": 6,
            "IsPartOfSeries": true,
            "IsPartialRecording": true,
            "IsPremiere": false,
            "IsRepeat": false,
            "KeepUntilMode": 0,
            "KeepUntilValue": null,
            "LastWatchedPosition": null,
            "LastWatchedTime": null,
            "PendingDelete": false,
            "ProgramStartTime": "/Date(1330655400000-0600)/",
            "ProgramStopTime": "/Date(1330657200000-0600)/",
            "Rating": "TV-PG",
            "RecordingFileFormatId": null,
            "RecordingFileName": "\\\\ONYX\\ForTheRecord\\Recordings\\Up All Night - New Boss (2012-03-01 20__1.ts",
            "RecordingId": "972f5480-0fa4-4700-83cc-4f0f4c377a68",
            "RecordingStartTime": "/Date(1330655525000-0600)/",
            "RecordingStopTime": "/Date(1330657231000-0600)/",
            "ScheduleId": "b5ae38c0-7d32-4f69-8810-370e74b73e65",
            "ScheduleName": "Up All Night",
            "SchedulePriority": 1,
            "SeriesNumber": 1,
            "StarRating": null,
            "SubTitle": "New Boss",
            "Title": "Up All Night"
        }
     */           
    
    public void init(File uncRecordingFile)
    {                                                                                                                    
        this.recordingFile = uncRecordingFile;
        originalPath = uncRecordingFile.getAbsolutePath();//should be full UNC path
        
        //use FilenameUtils to extract some info about the file's name/path
        extension = FilenameUtils.getExtension(uncRecordingFile.getName());
        pathNoExtension = FilenameUtils.removeExtension(uncRecordingFile.getAbsolutePath());
        baseName = FilenameUtils.getBaseName(uncRecordingFile.getName());
                
        //parse custom info from Description using regex
        //such as: [S02E19E20] [y:2009] [tvdb:116291]
        //check for mutli-part matches, which are put into the description by XMLTVDB
        seasonEpisodeNaming = valid(Description) ? getRegexMatch("\\[((S|E)[0-9]+)+\\]", Description) : null;        
        if(valid(seasonEpisodeNaming))
        {
            isMultiPart = true;//season/episode naming is only specified in description when it's multi-part
            seasonEpisodeNaming = seasonEpisodeNaming.substring(1,seasonEpisodeNaming.length()-1);//trim the []            
        }
        else
        {//not multi-part, build the seasonEpisodeNaming normally
            
            isMultiPart = false;
            if(!isMovie())
            {
                if(SeriesNumber==null || SeriesNumber.intValue() < 0)      
                {
                    Logger.WARN("SeriesNumber not found in 4tr meta data!");            
                    EpisodeNumber=null;//dont use either if one isn't avail
                }
                if(EpisodeNumber==null || EpisodeNumber.intValue() < 0)
                {
                    Logger.WARN("EpisodeNumber not found in 4tr meta data, will attempt to parse from EpisodeNumberDisplay: \""+EpisodeNumberDisplay+"\"");
                    if(valid(EpisodeNumberDisplay))
                    {
                        EpisodeNumberDisplay = EpisodeNumberDisplay.toUpperCase();
                        String SxxExx = getRegexMatch("S[0-9]+E[0-9]+", EpisodeNumberDisplay);
                        if(valid(SxxExx))
                        {
                            SeriesNumber = Integer.parseInt(SxxExx.substring(1, SxxExx.indexOf("E")));
                            EpisodeNumber = Integer.parseInt(SxxExx.substring(SxxExx.indexOf("E")+1,SxxExx.length()));
                            seasonEpisodeNaming = "S"+padInt(SeriesNumber)+"E"+padInt(EpisodeNumber);
                            Logger.INFO("Season="+SeriesNumber+", Episode="+EpisodeNumber+ " (parsed from: "+ EpisodeNumberDisplay+")");
                        }
                        else
                            Logger.WARN("Not valid SxxExx format: \""+EpisodeNumberDisplay+"\". Cannot parse.");                                                
                    }
                    else
                    {
                        Logger.WARN("Cannot get SeriesNumber from <SeriesNumber> or <EpisodeNumberDisplay> in 4tr meta data for recording: "+ recordingFile);                        
                        SeriesNumber=null;//dont use either if one isn't avail
                        EpisodeNumber=null;
                    }
                }
                else//season and episode numbers are available in the json
                    seasonEpisodeNaming = "S"+padInt(SeriesNumber)+"E"+padInt(EpisodeNumber);
            }
        }
        
        year = getRegexMatch("\\[y:[0-9]+\\]", Description);
        if(valid(year))
            year = year.substring("[y:".length(),year.length()-1);//trim the [y:]
        
        tvdbId = getRegexMatch("\\[tvdb:[0-9]+\\]", Description);
        if(valid(tvdbId))
            tvdbId = tvdbId.substring("[tvdb:".length(),tvdbId.length()-1);//trim the [tvdb:]                                                                                        
    }
     
    
    public void setSpecial(int seasonZeroEpisodeNumber)
    {
        manuallyArchived = true;
        SeriesNumber = 0;
        EpisodeNumber = seasonZeroEpisodeNumber;
    }
    public boolean isManuallyArchived()
    {
        return manuallyArchived;
    }
    public boolean seasonEpisodeAvailable()
    {
        return valid(seasonEpisodeNaming);
    }
    
    public String getSeasonEpisodeNaming()
    {
        return seasonEpisodeNaming;
    }
            
    public boolean hasEpisodeTitle()
    {
        return valid(getEpisodeTitle());
    }
    public String getEpisodeTitle()
    {
        return SubTitle;
    }
    public void setEpisodeTitle(String episodeTitle)
    {
        this.SubTitle = episodeTitle;
    }
    
    public String getSeriesName()
    {
        return Title;
    }
    public String getMovieTitle()
    {
        return Title;
    }
    public boolean isMovie()
    {
        return FTR_MOVIE_CATEGORY.equalsIgnoreCase(getCategory());
    }
    
    public boolean isYearAvailable()
    {
        return valid(getYear());
    }
    public String getYear()
    {
        return year;
    }
    public int getSeasonNumber()
    {
        return SeriesNumber == null ? -1 : SeriesNumber.intValue();
    }
    public int getEpisodeNumber()
    {
        return EpisodeNumber==null ? -1 : EpisodeNumber.intValue();
    }
    public boolean hasTVDBId()
    {
        return valid(getTVDBId());
    }
    public String getTVDBId()
    {
        return tvdbId;
    }
    
    public boolean isPatrialRecording()
    {
        return IsPartialRecording;
    }
    public boolean isMultiPart()
    {
        return isMultiPart;
    }
    
    //trim the full recording time to the day only
    static SimpleDateFormat airedDateSDF = new SimpleDateFormat("yyyy-MM-dd");
    public String getAiredDate()
    {
                
        if(RecordingStartTime != null)
            //Sample: 2012-02-20      
            return airedDateSDF.format(RecordingStartTime);
        else 
            return null;
    }
    
    //split actors string to return List
    public List<String> getActors()
    {
        List<String> actors = new ArrayList<String>();
        if(valid(Actors))
        {
            //4tr splits names using semicolon       
            actors.addAll(Arrays.asList(splitLiteralDelim(Actors, ";")));                        
        }
        return actors;
    }
    
    public boolean hasDescription()
    {
        return valid(Description);
    }
    public String getDescription()
    {
        return Description;
    }
    
    public boolean hasRating()
    {
        return valid(Rating);
    }
    public String getRating()
    {
        return Rating;
    }

    public boolean hasCategory()
    {
        return valid(Category);
    }
    public String getCategory() {
        return Category;
    }

    public boolean hasChannelDeisplayName(){
        return valid(ChannelDisplayName);
    }
    public String getChannelDisplayName() {
        return ChannelDisplayName;
    }
    public String getRecordingId() {
        return RecordingId;
    }                       
    
    public String getScheduleId()
    {
        return ScheduleId;
    }
    
     public String getExtension() {
        return extension;
    }

    public String getPathNoExtension() {
        return pathNoExtension;
    }

    public String getBaseName() {
        return baseName;
    }

    public File getRecordingFile() {
        return recordingFile;
    }

    public String getOriginalPath() {
        return originalPath;
    }
    
}
